﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bepo.Model.Data;
using Framework;

namespace Bepo.Model.Setup
{
    public class SetupHelper
    {
        public void Run()
        {
            new LogEvent("SetupHelper.Run").Raise();
            EnsureSetupTasksTable();
            var lastSetup = GetLastSetupDate();
            var tasksToRun = GetTasks(lastSetup);

            new LogEvent(tasksToRun.Count() + " tasks to Run").Raise();
            foreach (var task in tasksToRun.ToList())
            {
                var setupTask = new SetupTaskRecord { Id = Comb.NewGuid(), Name = task.GetType().Name, DevelopedOn = task.DevelopedOn, SetupOn = DateTime.UtcNow, IsSuccess = false };
                setupTask.Save();
                try
                {
                    task.Run();
                    setupTask.IsSuccess = true;
                    setupTask.Save();
                }
                catch (Exception x)
                {
                    new LogEvent(x).Raise();
                    break;
                }
            }
        }

        void EnsureSetupTasksTable()
        {
            var script = string.Empty;

            script = @"
			    if( object_id('SetupTask') is not null) begin
				    DROP TABLE [dbo].[SetupTask]
			    end";

            Core.DatabaseDirect.ExecuteScript(script);


            script = @"
			    if( object_id('SetupTask') is null) begin
				    CREATE TABLE [dbo].[SetupTask](
					    [Id] [uniqueidentifier] NOT NULL,
					    [Name] [nvarchar](255) NOT NULL,
					    [IsSuccess] [bit] NOT NULL,
					    [DevelopedOn] [smalldatetime] NOT NULL,
					    [SetupOn] [smalldatetime] NOT NULL,
					     CONSTRAINT [PK_SetupTask] PRIMARY KEY CLUSTERED 
					    (
						    [Id] ASC
					    )
				    )
			    end";

            Core.DatabaseDirect.ExecuteScript(script);
        }

        DateTime? GetLastSetupDate()
        {
            var script = "select max(DevelopedOn) from SetupTask where IsSuccess = 1";
            var result = Core.DatabaseDirect.ExecuteScalar(script);
            return (DateTime?)result;
        }

        IEnumerable<ISetupTask> GetTasks(DateTime? lastSetup)
        {
            var setupTaskTypes = AppDomain
                .CurrentDomain
                .GetAssemblies()
                .SelectMany(x => x.GetExportedTypes())
                .Where(x => !(x.IsAbstract || x.IsInterface) && x.GetInterfaces().Contains(typeof(ISetupTask)));

            return setupTaskTypes
                .Select(x => (ISetupTask)Activator.CreateInstance(x))
                .Where(x => (!lastSetup.HasValue) || (x.DevelopedOn > lastSetup.Value))
                .OrderBy(x => x.DevelopedOn);
        }
    }
}
